/**
 * Project 68th
 */

#include "../include/log4cppuse.h"
#include "../include/TcpConnection.h"
#include "../include/EventLoop.h"
#include <sstream>
using std::ostringstream;



/**
 * TcpConnection implementation
 */


/**
 * @param fd
 */
TcpConnection::TcpConnection(int fd,EventLoop * loop) 
: _loop(loop)
, _sockIO(fd)
, _sock(fd)
, _localAddr(getLocalAddr())
, _peerAddr(getPeerAddr())
{

}

TcpConnection::~TcpConnection() {

}

/**
 * @return string
 */
string TcpConnection::receive() {
    char buff[65535] = {0};
    _sockIO.readLine(buff,sizeof(buff));
    return string(buff);
}

Message TcpConnection::receiveMessage() {
    Message message=_sockIO.readMessage();
    
    if(message.isEmpty()) {
        LOG_ERROR("TcpConnection 接收空消息");
        return Message();
    }

    return message;
}

/**
 * @param msg
 * @return void
 */
void TcpConnection::send(const Message & message) {
    _sockIO.writenMessage(message);
}


void TcpConnection::sendInLoop(const Message & message)
{
    if(_loop)
    {
        _loop->runInLoop(bind(&TcpConnection::send,this,message));
    }
}

string TcpConnection::toString()
{
    ostringstream oss;
    oss << _localAddr.getIp() << ":"
        << _localAddr.getPort() << " ----> "
        << _peerAddr.getIp() << ":"
        << _peerAddr.getPort();
    return oss.str();
}

InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    int ret = getsockname(_sock.getFd(),(struct sockaddr*)&addr,&len);
    if(ret < 0)
    {
        LOG_ERROR("TcpConnection 获取本地地址失败");
    }

    return InetAddress(addr);
}

InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    int ret = getpeername(_sock.getFd(),(struct sockaddr*)&addr,&len);
    if(ret < 0)
    {
        LOG_ERROR("TcpConnection 获取对端地址失败");
    }

    return InetAddress(addr);
}

//先进行一次复制式的预读取
//如果读到的字符数为0，说明客户端下线了
bool TcpConnection::isClosed()
{
    char buff[20] = {0};
    int ret = ::recv(_sock.getFd(),buff,sizeof(buff),MSG_PEEK);
    return ret == 0;
}


void TcpConnection::setNewConnectionCallback(const TcpConnectionCallback & cb)
{
    //如果此处使用移动赋值，那么创建的第一个TcpConnection中
    //的function就会抢占EventLoop中function原本关联的目标
    //这样的话，第二次建立连接时，EventLoop中的function已经是
    //空的function，再做转接工作，第二个TcpConnection的function
    //也会是空的function，并没有正确地注册回调函数

    /* _onNewConnection = std::move(cb); */
    _onNewConnection = cb;
}
void TcpConnection::setMessageCallback(const TcpConnectionCallback & cb)
{
    _onMessage = cb;
}
void TcpConnection::setCloseCallback(const TcpConnectionCallback & cb)
{
    _onClose = cb;
}

void TcpConnection::handleNewConnectionCallback()
{
    if(_onNewConnection){
        /* _onNewConnection(shared_ptr<TcpConnection>(this)); */
        _onNewConnection(shared_from_this());
    }
    else
    {
        LOG_ERROR("TcpConnection 新连接回调函数为空");
    }
}
void TcpConnection::handleMessageCallback()
{
    if(_onMessage){
        _onMessage(shared_from_this());
    }
    else
    {
        LOG_ERROR("TcpConnection 消息回调函数为空");
    }
}
void TcpConnection::handleCloseCallback()
{
    if(_onClose){
        _onClose(shared_from_this());
    }
    else
    {
        LOG_ERROR("TcpConnection 关闭回调函数为空");
    }
}
